package UIUtils.Exif
{
	import com.adobe.utils.DateUtil;
	
	import flash.utils.ByteArray;
	
	import mx.formatters.DateFormatter;

	public class ExifHeader extends ByteArray {
		
		public function ExifHeader(ExifData: Object): void {
			super();
			
			writeBytesA(Tags.APP1_MAKER);
			writeWord(0); // Сохраняем длинну, пока пустую
			
			writeBytesA(Tags.EXIF_HEADER);
			
			writeWord(0x4D4D);
			writeWord(0x002A);
			writeInt(0x00000008);
			writeWord(0x0008);			
			
			writeData(ExifData);
			while (length < 200) writeByte(0);
			position = Tags.APP1_MAKER.length;
			writeWord(length - 2);
		}
		
		public static function currenDate(): String {
			var df: DateFormatter = new DateFormatter();
			df.formatString = 'YYYY:MM:DD HH:NN:SS';
			return df.format(new Date());
		}

/*		
		protected function toUnicode(s: String): String {
			var result: String = '';
			for (var i: int=0; i<s.length; i++) {
				var code: uint = s.charCodeAt(i);
				var c1: uint = code >> 8;
				var c2: uint = code & 0xFF;
				result += String.fromCharCode(c2);
				result += c1?String.fromCharCode(c1):0;
			}
			return result;
		}
*/		
		
		protected function writeData(ExifData: Object): void {
			var hpLen	: uint = 0;
			var fdata	: Array = [];
			var tags	: Object = Tags;
			var p		: String;
			
			for (p in ExifData) {
				var property: String = p.toUpperCase();
				if (tags[property]) {
					var s: String = ExifData[p];
//					if (s.charCodeAt(0) > 0xFF)  s = toUnicode(s);
					fdata.push({
						name	: property,
						data	: s,
						code	: tags[property],
						len		: s.length * tags.BYTESPERTYPE[tags.TYPES[property]]
					});
					hpLen += 12;
				}
			}
			
			fdata.sortOn('code');
			
			var dpLen	: int = 0;
			var i		: int;
			for (i=0;i<fdata.length;i++) {
				p = fdata[i].name;  
				var offset: int = 10 + hpLen + dpLen;
				var type: uint = tags.TYPES[p];
				var len: int = fdata[i].len + ((type == Tags.STRINGTYPE)?1:0);
				dpLen += len;
				
				writeWord(fdata[i].code);
				writeWord(type);
				writeUnsignedInt(len);
				writeUnsignedInt(offset);
			}

			for (i=0;i<fdata.length;i++) {
				writeAsType(fdata[i].data, tags.TYPES[fdata[i].name]);
			}
		}
		
		protected function writeWord(word: int): void {
			writeByte((word & 0xFF00) >> 8);
			writeByte(word & 0xFF);
		}
		
		protected function writeBytesA(a: Array): void {
			for (var i: int= 0; i<a.length; i++)
				writeByte(a[i]);
		}
		
		protected function writeAsString(s: String): void {
			for (var i: int= 0; i<s.length; i++) {
				writeByte(s.charCodeAt(i));
			}
			writeByte(0);
		}
		
		protected function writeAsInt8(s: String): void {
			for (var i: int= 0; i<s.length; i++) {
				writeWord(s.charCodeAt(i) << 8)
			}
		}
		
		protected function writeAsType(s: Object, type: int): void {
			switch (type) {
				case Tags.INT8UTYPE:  writeAsInt8(s as String);
					break;
				case Tags.STRINGTYPE: writeAsString(s as String);
					break;
			}
		}
	}
}